<?php
    // +----------------------------------------------------------------------
    // | 海豚PHP框架 [ DolphinPHP ]
    // +----------------------------------------------------------------------
    // | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
    // +----------------------------------------------------------------------
    // | 官方网站: http://dolphinphp.com
    // +----------------------------------------------------------------------
    // | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
    // +----------------------------------------------------------------------

    use think\Db;
    use think\View;
    use app\user\model\User;

    if (!function_exists('is_swoole')) {
        /**
         * 判断是否为swoole运行
         * @return bool
         */
        function is_swoole()
        {
            return strpos(\think\facade\Request::server('SERVER_SOFTWARE'), 'swoole') !== false;
        }
    }

    if (!function_exists('result')) {
        /**
         * 创建普通 Response 对象实例
         * @param mixed $data 输出数据
         * @param int|string $code 状态码
         * @param string $msg
         * @param string $type
         */
        function result($data = [], $code = 200, $msg = '', $type = 'json')
        {
            \think\facade\Log::record(json_encode(['titile' => '日志', 'msg' => $msg, '']));

            $result = [
                'code' => $code,
                'msg'  => $msg,
                'time' => \think\facade\Request::time(),
                'data' => $data,
            ];
            throw new \think\exception\HttpResponseException(\think\facade\Response::create($result, $type)->header(['auth-token-status' => 0]));

        }
    }
    if (!function_exists('error')) {
        /**
         * 操作错误跳转的快捷方法
         * @param string $msg
         * @param string $data
         */
        function error($msg = 'error', $data = '')
        {
            result($data, 500, $msg, 'json');
        }
    }
    if (!function_exists('success')) {
        /**
         * 操作成功跳转的快捷方法
         * @param string $msg
         * @param string $data
         */
        function success($msg = 'success', $data = '')
        {
            result($data, 200, $msg, 'json');
        }
    }

    if (!function_exists('in_string')) {
        // 应用公共文件
        function in_string($str2, $str1)
        {
            if (strpos($str1, $str2) !== -1) {
                return true;
            }
            return false;
        }
    }

    if (!function_exists('getLastSql')) {
        function getLastSql()
        {
            dump(Db::getLastSql());
        }
    }
    if (!function_exists('ExceptionMail')) {
        /**
         * @param $html
         * @throws \PHPMailer\PHPMailer\Exception
         */
        function ExceptionMail(\think\Exception $exception)
        {
            $j    = new  \app\common\exce\JsonHandle();
            $data = $j->render($exception);
            ob_start();
            dump($data);
            $html       = ob_get_clean();
            $MailConfig = config('mail');

            $mail = new \PHPMailer\PHPMailer\PHPMailer(); //实例化
            $mail->IsSMTP(); // 启用SMTP
            $mail->Host     = $MailConfig['smtp_host']; //SMTP服务器 163邮箱例子
            $mail->Port     = $MailConfig['smtp_port'];  //邮件发送端口
            $mail->SMTPAuth = true;  //启用SMTP认证
            $MailConfig['ssl'] ? $mail->SMTPSecure = 'ssl' : null;
            $mail->CharSet  = "UTF-8"; //字符集
            $mail->Encoding = "base64"; //编码方式
            $mail->Username = $MailConfig['Username'];  //你的邮箱
            $mail->Password = $MailConfig['Password'];  //你的密码
            $mail->Subject  = "系统出错了，赶快来检查"; //邮件标题
            $mail->From     = $MailConfig['Username'];  //发件人地址（也就是你的邮箱）
            $mail->FromName = "系统消息";   //发件人姓名

            foreach ($MailConfig['Exception']['addresses'] as $address) {
                $mail->AddAddress($address['address'], $address['name']);    //添加收件人1（地址，昵称）s
            }
            $mail->IsHTML(true); //支持html格式内容
            $mail->Body = '你好, <b>朋友</b>! <br/>这是一封系统邮件！你的系统出错了！赶快检查<br>' . $html; //邮件主体内容

            if (!$mail->send()) {
                echo 'Message could not be sent.';
                echo 'Mailer Error: ' . $mail->ErrorInfo;

            }
            echo '发送成功！';
        }
    }

    if (!function_exists('defaultd')) {
        /**
         * 判断是否登录
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return mixed
         */
        function defaultd($data, $value = '')
        {
            if ($data != '' & !empty($data)) {
                return $data;
            } else {
                return $value;
            }
        }
    }

    if (!function_exists('tlog')) {
        /**
         * 判断是否登录
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return mixed
         */
        function tlog($data)
        {

            $string = json_encode($data) . PHP_EOL;
            file_put_contents(Env::get('runtime_path') . 'log/test.log', $string, FILE_APPEND);
        }
    }
    if (!function_exists('view_money')) {
        /**
         * 判断是否登录
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return mixed
         */
        function view_money(int $money)
        {

            return $money / 100;
        }
    }

    if (!function_exists('is_signin')) {
        /**
         * 判断是否登录
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return mixed
         */
        function is_signin()
        {

            $user = session('user_auth');
            if (empty($user)) {
                // 判断是否记住登录
                if (cookie('?uid') && cookie('?signin_token')) {
                    $UserModel = new User();
                    $user      = $UserModel::get(cookie('uid'));
                    if ($user) {
                        $signin_token = data_auth_sign($user['username'] . $user['id'] . $user['last_login_time']);
                        if (cookie('signin_token') == $signin_token) {
                            // 自动登录
                            $UserModel->autoLogin($user);
                            return $user['id'];
                        }
                    }
                };
                return 0;
            } else {
                return session('user_auth_sign') == data_auth_sign($user) ? $user['uid'] : 0;
            }
        }
    }

    if (!function_exists('data_auth_sign')) {
        /**
         * 数据签名认证
         *
         * @param array $data 被认证的数据
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return string
         */
        function data_auth_sign($data = [])
        {

            // 数据类型检测
            if (!is_array($data)) {
                $data = (array)$data;
            }

            // 排序
            ksort($data);
            // url编码并生成query字符串
            $code = http_build_query($data);
            // 生成签名
            $sign = sha1($code);
            return $sign;
        }
    }

    if (!function_exists('get_file_path')) {
        /**
         * 获取附件路径
         *
         * @param int $id 附件id
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return string
         */
        function get_file_path($id = 0)
        {

            $path = model('admin/attachment')->getFilePath($id);
            if (!$path) {
                return 'http://timeappthree.ssjtime.cn/de25e9b677dc186b92bb09a462061557.png?v=807036';
                //return config('public_static_path') . 'admin/img/none.png';
            }
            return $path;
        }
    }

    if (!function_exists('get_files_path')) {
        /**
         * 批量获取附件路径
         *
         * @param array $ids 附件id
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return array
         */
        function get_files_path($ids = [])
        {

            $ids   = explode(',', $ids);
            $paths = model('admin/attachment')->getFilePath($ids);
            return !$paths ? [] : $paths;
        }
    }

    if (!function_exists('get_thumb')) {
        /**
         * 获取图片缩略图路径
         *
         * @param int $id 附件id
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return string
         */
        function get_thumb($id = 0)
        {

            $path = model('admin/attachment')->getThumbPath($id);
            if (!$path) {
                return config('public_static_path') . 'admin/img/none.png';
            }
            return $path;
        }
    }

    if (!function_exists('get_avatar')) {
        /**
         * 获取用户头像路径
         *
         * @param int $uid 用户id
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @alter  小乌 <82950492@qq.com>
         * @return string
         */
        function get_avatar($uid = 0)
        {

            $avatar = Db::name('admin_user')->where('id', $uid)->value('avatar');
            $path   = model('admin/attachment')->getFilePath($avatar);
            if (!$path) {
                return '/static/admin/img/avatar.jpg';
            }
            return $path;
        }
    }

    if (!function_exists('get_file_name')) {
        /**
         * 根据附件id获取文件名
         *
         * @param string $id 附件id
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return string
         */
        function get_file_name($id = '')
        {

            $name = model('admin/attachment')->getFileName($id);
            if (!$name) {
                return '没有找到文件';
            }
            return $name;
        }
    }

    if (!function_exists('minify')) {
        /**
         * 合并输出js代码或css代码
         *
         * @param string $type 类型：group-分组，file-单个文件，base-基础目录
         * @param string $files 文件名或分组名
         *
         * @author 蔡伟明 <314013107@qq.com>
         */
        function minify($type = '', $files = '')
        {

            $files = !is_array($files) ? $files : implode(',', $files);
            $url   = \think\facade\Env::get('root_path') . 'public/' . 'min/?';

            switch ($type) {
                case 'group':
                    $url .= 'g=' . $files;
                    break;
                case 'file':
                    $url .= 'f=' . $files;
                    break;
                case 'base':
                    $url .= 'b=' . $files;
                    break;
            }
            echo $url . '&v=' . config('asset_version');
        }
    }

    if (!function_exists('ck_js')) {
        /**
         * 返回ckeditor编辑器上传文件时需要返回的js代码
         *
         * @param string $callback 回调
         * @param string $file_path 文件路径
         * @param string $error_msg 错误信息
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return string
         */
        function ck_js($callback = '', $file_path = '', $error_msg = '')
        {

            return "<script type='text/javascript'>window.parent.CKEDITOR.tools.callFunction($callback, '$file_path' , '$error_msg');</script>";
        }
    }

    if (!function_exists('parse_attr')) {
        /**
         * 解析配置
         *
         * @param string $value 配置值
         *
         * @return array|string
         */
        function parse_attr($value = '')
        {

            $array = preg_split('/[,;\r\n]+/', trim($value, ",;\r\n"));
            if (strpos($value, ':')) {
                $value = [];
                foreach ($array as $val) {
                    list($k, $v) = explode(':', $val);
                    $value[$k] = $v;
                }
            } else {
                $value = $array;
            }
            return $value;
        }
    }

    if (!function_exists('implode_attr')) {
        /**
         * 组合配置
         *
         * @param array $array 配置值
         *
         * @return string
         */
        function implode_attr($array = [])
        {

            $result = [];
            foreach ($array as $key => $value) {
                $result[] = $key . ':' . $value;
            }
            return empty($result) ? '' : implode(PHP_EOL, $result);
        }
    }

    if (!function_exists('parse_array')) {
        /**
         * 将一维数组解析成键值相同的数组
         *
         * @param array $arr 一维数组
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return array
         */
        function parse_array($arr)
        {

            $result = [];
            foreach ($arr as $item) {
                $result[$item] = $item;
            }
            return $result;
        }
    }

    if (!function_exists('parse_config')) {
        /**
         * 解析配置，返回配置值
         *
         * @param array $configs 配置
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return array
         */
        function parse_config($configs = [])
        {

            $type   = [
                'hidden'      => 2,
                'date'        => 4,
                'ckeditor'    => 4,
                'daterange'   => 4,
                'datetime'    => 4,
                'editormd'    => 4,
                'file'        => 4,
                'colorpicker' => 4,
                'files'       => 4,
                'icon'        => 4,
                'image'       => 4,
                'images'      => 4,
                'jcrop'       => 4,
                'range'       => 4,
                'number'      => 4,
                'password'    => 4,
                'sort'        => 4,
                'static'      => 4,
                'summernote'  => 4,
                'switch'      => 4,
                'tags'        => 4,
                'text'        => 4,
                'array'       => 4,
                'textarea'    => 4,
                'time'        => 4,
                'ueditor'     => 4,
                'wangeditor'  => 4,
                'radio'       => 5,
                'bmap'        => 5,
                'masked'      => 5,
                'select'      => 5,
                'linkage'     => 5,
                'checkbox'    => 5,
                'linkages'    => 6
            ];
            $result = [];
            foreach ($configs as $item) {
                // 判断是否为分组
                if ($item[0] == 'group') {
                    foreach ($item[1] as $option) {
                        foreach ($option as $group => $val) {
                            $result[$val[1]] = isset($val[$type[$val[0]]]) ? $val[$type[$val[0]]] : '';
                        }
                    }
                } else {
                    $result[$item[1]] = isset($item[$type[$item[0]]]) ? $item[$type[$item[0]]] : '';
                }
            }
            return $result;
        }
    }

    if (!function_exists('set_config_value')) {
        /**
         * 设置配置的值，并返回配置好的数组
         *
         * @param array $configs 配置
         * @param array $values 配置值
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return array
         */
        function set_config_value($configs = [], $values = [])
        {

            $type = [
                'hidden'      => 2,
                'date'        => 4,
                'ckeditor'    => 4,
                'daterange'   => 4,
                'datetime'    => 4,
                'editormd'    => 4,
                'file'        => 4,
                'colorpicker' => 4,
                'files'       => 4,
                'icon'        => 4,
                'image'       => 4,
                'images'      => 4,
                'jcrop'       => 4,
                'range'       => 4,
                'number'      => 4,
                'password'    => 4,
                'sort'        => 4,
                'static'      => 4,
                'summernote'  => 4,
                'switch'      => 4,
                'tags'        => 4,
                'text'        => 4,
                'array'       => 4,
                'textarea'    => 4,
                'time'        => 4,
                'ueditor'     => 4,
                'wangeditor'  => 4,
                'radio'       => 5,
                'bmap'        => 5,
                'masked'      => 5,
                'select'      => 5,
                'linkage'     => 5,
                'checkbox'    => 5,
                'linkages'    => 6
            ];

            foreach ($configs as &$item) {
                // 判断是否为分组
                if ($item[0] == 'group') {
                    foreach ($item[1] as &$option) {
                        foreach ($option as $group => &$val) {
                            $val[$type[$val[0]]] = isset($values[$val[1]]) ? $values[$val[1]] : '';
                        }
                    }
                } else {
                    $item[$type[$item[0]]] = isset($values[$item[1]]) ? $values[$item[1]] : '';
                }
            }
            return $configs;
        }
    }

    if (!function_exists('hook')) {
        /**
         * 监听钩子
         *
         * @param string $name 钩子名称
         * @param mixed $params 传入参数
         * @param bool $once 只获取一个有效返回值
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @alter  小乌 <82950492@qq.com>
         */
        function hook($name = '', $params = null, $once = false)
        {

            \think\facade\Hook::listen($name, $params, $once);
        }
    }

    if (!function_exists('module_config')) {
        /**
         * 显示当前模块的参数配置页面，或获取参数值，或设置参数值
         *
         * @param string $name
         * @param string $value
         *
         * @author caiweiming <314013107@qq.com>
         * @return mixed
         */
        function module_config($name = '', $value = '')
        {

            if ($name === '') {
                // 显示模块配置页面
                return action('admin/admin/moduleConfig');
            } elseif ($value === '') {
                // 获取模块配置
                if (strpos($name, '.')) {
                    list($name, $item) = explode('.', $name);
                    return model('admin/module')->getConfig($name, $item);
                } else {
                    return model('admin/module')->getConfig($name);
                }
            } else {
                // 设置值
                return model('admin/module')->setConfig($name, $value);
            }
        }
    }

    if (!function_exists('plugin_menage')) {
        /**
         * 显示插件的管理页面
         *
         * @param string $name 插件名
         *
         * @author caiweiming <314013107@qq.com>
         * @return mixed
         */
        function plugin_menage($name = '')
        {

            return action('admin/plugin/manage', ['name' => $name]);
        }
    }

    if (!function_exists('plugin_config')) {
        /**
         * 获取或设置某个插件配置参数
         *
         * @param string $name 插件名.配置名
         * @param string $value 设置值
         *
         * @author caiweiming <314013107@qq.com>
         * @return mixed
         */
        function plugin_config($name = '', $value = '')
        {

            if ($value === '') {
                // 获取插件配置
                if (strpos($name, '.')) {
                    list($name, $item) = explode('.', $name);
                    return model('admin/plugin')->getConfig($name, $item);
                } else {
                    return model('admin/plugin')->getConfig($name);
                }
            } else {
                return model('admin/plugin')->setConfig($name, $value);
            }
        }
    }

    if (!function_exists('get_plugin_class')) {
        /**
         * 获取插件类名
         *
         * @param  string $name 插件名
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return string
         */
        function get_plugin_class($name)
        {

            return "plugins\\{$name}\\{$name}";
        }
    }

    if (!function_exists('get_client_ip')) {
        /**
         * 获取客户端IP地址
         *
         * @param int $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
         * @param bool $adv 是否进行高级模式获取（有可能被伪装）
         *
         * @return mixed
         */
        function get_client_ip($type = 0, $adv = false)
        {

            $type = $type ? 1 : 0;
            static $ip = NULL;
            if ($ip !== NULL)
                return $ip[$type];
            if ($adv) {
                if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                    $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                    $pos = array_search('unknown', $arr);
                    if (false !== $pos)
                        unset($arr[$pos]);
                    $ip = trim($arr[0]);
                } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
                    $ip = $_SERVER['HTTP_CLIENT_IP'];
                } elseif (isset($_SERVER['REMOTE_ADDR'])) {
                    $ip = $_SERVER['REMOTE_ADDR'];
                }
            } elseif (isset($_SERVER['REMOTE_ADDR'])) {
                $ip = $_SERVER['REMOTE_ADDR'];
            }
            // IP地址合法验证
            $long = sprintf("%u", ip2long($ip));
            $ip   = $long ? [$ip, $long] : ['0.0.0.0', 0];
            return $ip[$type];
        }
    }

    if (!function_exists('format_bytes')) {
        /**
         * 格式化字节大小
         *
         * @param  number $size 字节数
         * @param  string $delimiter 数字和单位分隔符
         *
         * @return string            格式化后的带单位的大小
         * @author 麦当苗儿 <zuojiazi@vip.qq.com>
         */
        function format_bytes($size, $delimiter = '')
        {

            $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
            for ($i = 0; $size >= 1024 && $i < 5; $i++)
                $size /= 1024;
            return round($size, 2) . $delimiter . $units[$i];
        }
    }

    if (!function_exists('format_time')) {
        /**
         * 时间戳格式化
         *
         * @param string $time 时间戳
         * @param string $format 输出格式
         *
         * @return false|string
         */
        function format_time($time = '', $format = 'Y-m-d H:i')
        {

            return !$time ? '' : date($format, intval($time));
        }
    }

    if (!function_exists('format_date')) {
        /**
         * 使用bootstrap-datepicker插件的时间格式来格式化时间戳
         * @param null $time 时间戳
         * @param string $format bootstrap-datepicker插件的时间格式 https://bootstrap-datepicker.readthedocs.io/en/stable/options.html#format
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return false|string
         */
        function format_date($time = null, $format = 'yyyy-mm-dd')
        {

            $format_map = [
                'yyyy' => 'Y',
                'yy'   => 'y',
                'MM'   => 'F',
                'M'    => 'M',
                'mm'   => 'm',
                'm'    => 'n',
                'DD'   => 'l',
                'D'    => 'D',
                'dd'   => 'd',
                'd'    => 'j',
            ];

            // 提取格式
            preg_match_all('/([a-zA-Z]+)/', $format, $matches);
            $replace = [];
            foreach ($matches[1] as $match) {
                $replace[] = isset($format_map[$match]) ? $format_map[$match] : '';
            }

            // 替换成date函数支持的格式
            $format = str_replace($matches[1], $replace, $format);
            $time   = $time === null ? time() : intval($time);
            return date($format, $time);
        }
    }
    if (!function_exists('format_dates')) {
        /**
         * 使用bootstrap-datepicker插件的时间格式来格式化时间戳
         * @param null $time 时间戳
         * @param string $format bootstrap-datepicker插件的时间格式 https://bootstrap-datepicker.readthedocs.io/en/stable/options.html#format
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return false|string
         */
        function format_dates($time = null, $format = 'Y-m-d H:i:s')
        {
            return date($format, $time);


        }
    }

    if (!function_exists('format_moment')) {
        /**
         * 使用momentjs的时间格式来格式化时间戳
         *
         * @param null $time 时间戳
         * @param string $format momentjs的时间格式
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return false|string
         */
        function format_moment($time = null, $format = 'YYYY-MM-DD HH:mm')
        {

            $format_map = [
                // 年、月、日
                'YYYY' => 'Y',
                'YY'   => 'y',
                //            'Y'    => '',
                'Q'    => 'I',
                'MMMM' => 'F',
                'MMM'  => 'M',
                'MM'   => 'm',
                'M'    => 'n',
                'DDDD' => '',
                'DDD'  => '',
                'DD'   => 'd',
                'D'    => 'j',
                'Do'   => 'jS',
                'X'    => 'U',
                'x'    => 'u',

                // 星期
                //            'gggg' => '',
                //            'gg' => '',
                //            'ww' => '',
                //            'w' => '',
                'e'    => 'w',
                'dddd' => 'l',
                'ddd'  => 'D',
                'GGGG' => 'o',
                //            'GG' => '',
                'WW'   => 'W',
                'W'    => 'W',
                'E'    => 'N',

                // 时、分、秒
                'HH'   => 'H',
                'H'    => 'G',
                'hh'   => 'h',
                'h'    => 'g',
                'A'    => 'A',
                'a'    => 'a',
                'mm'   => 'i',
                'm'    => 'i',
                'ss'   => 's',
                's'    => 's',
                //            'SSS' => '[B]',
                //            'SS'  => '[B]',
                //            'S'   => '[B]',
                'ZZ'   => 'O',
                'Z'    => 'P',
            ];

            // 提取格式
            preg_match_all('/([a-zA-Z]+)/', $format, $matches);
            $replace = [];
            foreach ($matches[1] as $match) {
                $replace[] = isset($format_map[$match]) ? $format_map[$match] : '';
            }

            // 替换成date函数支持的格式
            $format = str_replace($matches[1], $replace, $format);
            $time   = $time === null ? time() : intval($time);
            return date($format, $time);
        }
    }

    if (!function_exists('format_linkage')) {
        /**
         * 格式化联动数据
         *
         * @param array $data 数据
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return array
         */
        function format_linkage($data = [])
        {

            $list = [];
            foreach ($data as $key => $value) {
                $list[] = [
                    'key'   => $key,
                    'value' => $value
                ];
            }
            return $list;
        }
    }

    if (!function_exists('get_auth_node')) {
        /**
         * 获取用户授权节点
         *
         * @param int $uid 用户id
         * @param string $group 权限分组，可以以点分开模型名称和分组名称，如user.group
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return array|bool
         */
        function get_auth_node($uid = 0, $group = '')
        {

            return model('admin/access')->getAuthNode($uid, $group);
        }
    }

    if (!function_exists('check_auth_node')) {
        /**
         * 检查用户的某个节点是否授权
         *
         * @param int $uid 用户id
         * @param string $group $group 权限分组，可以以点分开模型名称和分组名称，如user.group
         * @param int $node 需要检查的节点id
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return bool
         */
        function check_auth_node($uid = 0, $group = '', $node = 0)
        {

            return model('admin/access')->checkAuthNode($uid, $group, $node);
        }
    }

    if (!function_exists('get_level_data')) {
        /**
         * 获取联动数据
         *
         * @param string $table 表名
         * @param  integer $pid 父级ID
         * @param  string $pid_field 父级ID的字段名
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return false|PDOStatement|string|\think\Collection
         */
        function get_level_data($table = '', $pid = 0, $pid_field = 'pid')
        {

            if ($table == '') {
                return '';
            }

            $data_list = Db::name($table)->where($pid_field, $pid)->select();

            if ($data_list) {
                return $data_list;
            } else {
                return '';
            }
        }
    }

    if (!function_exists('get_level_pid')) {
        /**
         * 获取联动等级和父级id
         *
         * @param string $table 表名
         * @param int $id 主键值
         * @param string $id_field 主键名
         * @param string $pid_field pid字段名
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return mixed
         */
        function get_level_pid($table = '', $id = 1, $id_field = 'id', $pid_field = 'pid')
        {

            return Db::name($table)->where($id_field, $id)->value($pid_field);
        }
    }

    if (!function_exists('get_level_key_data')) {
        /**
         * 反向获取联动数据
         *
         * @param string $table 表名
         * @param string $id 主键值
         * @param string $id_field 主键名
         * @param string $name_field name字段名
         * @param string $pid_field pid字段名
         * @param int $level 级别
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return array
         */
        function get_level_key_data($table = '', $id = '', $id_field = 'id', $name_field = 'name', $pid_field = 'pid', $level = 1)
        {

            $result             = [];
            $level_pid          = get_level_pid($table, $id, $id_field, $pid_field);
            $level_key[$level]  = $level_pid;
            $level_data[$level] = get_level_data($table, $level_pid, $pid_field);

            if ($level_pid != 0) {
                $data       = get_level_key_data($table, $level_pid, $id_field, $name_field, $pid_field, $level + 1);
                $level_key  = $level_key + $data['key'];
                $level_data = $level_data + $data['data'];
            }
            $result['key']  = $level_key;
            $result['data'] = $level_data;

            return $result;
        }
    }

    if (!function_exists('plugin_action_exists')) {
        /**
         * 检查插件控制器是否存在某操作
         *
         * @param string $name 插件名
         * @param string $controller 控制器
         * @param string $action 动作
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return bool
         */
        function plugin_action_exists($name = '', $controller = '', $action = '')
        {

            if (strpos($name, '/')) {
                list($name, $controller, $action) = explode('/', $name);
            }
            return method_exists("plugins\\{$name}\\controller\\{$controller}", $action);
        }
    }

    if (!function_exists('plugin_model_exists')) {
        /**
         * 检查插件模型是否存在
         *
         * @param string $name 插件名
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return bool
         */
        function plugin_model_exists($name = '')
        {

            return class_exists("plugins\\{$name}\\model\\{$name}");
        }
    }

    if (!function_exists('plugin_validate_exists')) {
        /**
         * 检查插件验证器是否存在
         *
         * @param string $name 插件名
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return bool
         */
        function plugin_validate_exists($name = '')
        {

            return class_exists("plugins\\{$name}\\validate\\{$name}");
        }
    }

    if (!function_exists('get_plugin_model')) {
        /**
         * 获取插件模型实例
         *
         * @param  string $name 插件名
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return object
         */
        function get_plugin_model($name)
        {

            $class = "plugins\\{$name}\\model\\{$name}";
            return new $class;
        }
    }

    if (!function_exists('plugin_action')) {
        /**
         * 执行插件动作
         * 也可以用这种方式调用：plugin_action('插件名/控制器/动作', [参数1,参数2...])
         *
         * @param string $name 插件名
         * @param string $controller 控制器
         * @param string $action 动作
         * @param mixed $params 参数
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return mixed
         */
        function plugin_action($name = '', $controller = '', $action = '', $params = [])
        {

            if (strpos($name, '/')) {
                $params = is_array($controller) ? $controller : (array)$controller;
                list($name, $controller, $action) = explode('/', $name);
            }
            if (!is_array($params)) {
                $params = (array)$params;
            }
            $class = "plugins\\{$name}\\controller\\{$controller}";
            $obj   = new $class;
            return call_user_func_array([$obj, $action], $params);
        }
    }

    if (!function_exists('_system_check')) {
        function _system_check()
        {

            $c = cache('_i_n_f_o');
            if (!$c || (time() - $c) > 86401) {
                cache('_i_n_f_o', time());
                $url                      = base64_decode('d3d3LmRvbHBoaW5waHAuY29tL3VwZGF0ZUluZm8=');
                $url                      = 'http://' . $url;
                $p['d' . 'om' . 'ain']    = request()->domain();
                $p[strtolower('I') . 'p'] = request()->server('SERVER_ADDR');
                $p                        = base64_encode(json_encode($p));

                $o = [
                    CURLOPT_TIMEOUT        => 20,
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_URL            => $url,
                    CURLOPT_USERAGENT      => request()->server('HTTP_USER_AGENT'),
                    CURLOPT_POST           => 1,
                    CURLOPT_POSTFIELDS     => ['p' => $p]
                ];

                if (function_exists('curl_init')) {
                    $c = curl_init();
                    curl_setopt_array($c, $o);
                    curl_exec($c);
                    curl_close($c);
                }
            }
        }
    }

    if (!function_exists('get_plugin_validate')) {
        /**
         * 获取插件验证类实例
         *
         * @param string $name 插件名
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return bool
         */
        function get_plugin_validate($name = '')
        {

            $class = "plugins\\{$name}\\validate\\{$name}";
            return new $class;
        }
    }

    if (!function_exists('plugin_url')) {
        /**
         * 生成插件操作链接
         *
         * @param string $url 链接：插件名称/控制器/操作
         * @param array $param 参数
         * @param string $module 模块名，admin需要登录验证，index不需要登录验证
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return string
         */
        function plugin_url($url = '', $param = [], $module = 'admin')
        {

            $params = [];
            $url    = explode('/', $url);
            if (isset($url[0])) {
                $params['_plugin'] = $url[0];
            }
            if (isset($url[1])) {
                $params['_controller'] = $url[1];
            }
            if (isset($url[2])) {
                $params['_action'] = $url[2];
            }

            // 合并参数
            $params = array_merge($params, $param);

            // 返回url地址
            return url($module . '/plugin/execute', $params);
        }
    }

    if (!function_exists('public_url')) {
        /**
         * 生成插件操作链接(不需要登陆验证)
         *
         * @param string $url 链接：插件名称/控制器/操作
         * @param array $param 参数
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return string
         */
        function public_url($url = '', $param = [])
        {

            // 返回url地址
            return plugin_url($url, $param, 'index');
        }
    }

    if (!function_exists('clear_js')) {
        /**
         * 过滤js内容
         *
         * @param string $str 要过滤的字符串
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return mixed|string
         */
        function clear_js($str = '')
        {

            $search = "/<script[^>]*?>.*?<\/script>/si";
            $str    = preg_replace($search, '', $str);
            return $str;
        }
    }

    if (!function_exists('get_nickname')) {
        /**
         * 根据用户ID获取用户昵称
         *
         * @param  integer $uid 用户ID
         *
         * @return string  用户昵称
         */
        function get_nickname($uid = 0)
        {

            static $list;
            // 获取当前登录用户名
            if (!($uid && is_numeric($uid))) {
                return session('user_auth.username');
            }

            // 获取缓存数据
            if (empty($list)) {
                $list = cache('sys_user_nickname_list');
            }

            // 查找用户信息
            $key = "u{$uid}";
            if (isset($list[$key])) {
                // 已缓存，直接使用
                $name = $list[$key];
            } else {
                // 调用接口获取用户信息
                $info = model('user/user')->field('nickname')->find($uid);
                if ($info !== false && $info['nickname']) {
                    $nickname = $info['nickname'];
                    $name     = $list[$key] = $nickname;
                    /* 缓存用户 */
                    $count = count($list);
                    $max   = config('user_max_cache');
                    while ($count-- > $max) {
                        array_shift($list);
                    }
                    cache('sys_user_nickname_list', $list);
                } else {
                    $name = '';
                }
            }
            return $name;
        }
    }

    if (!function_exists('action_log')) {
        /**
         * 记录行为日志，并执行该行为的规则
         *
         * @param null $action 行为标识
         * @param null $model 触发行为的模型名
         * @param string $record_id 触发行为的记录id
         * @param null $user_id 执行行为的用户id
         * @param string $details 详情
         *
         * @author huajie <banhuajie@163.com>
         * @alter  蔡伟明 <314013107@qq.com>
         * @return bool|string
         */
        function action_log($action = null, $model = null, $record_id = '', $user_id = null, $details = '')
        {

            // 判断是否开启系统日志功能
            if (config('system_log')) {
                // 参数检查
                if (empty($action) || empty($model)) {
                    return '参数不能为空';
                }
                if (empty($user_id)) {
                    $user_id = is_signin();
                }
                if (strpos($action, '.')) {
                    list($module, $action) = explode('.', $action);
                } else {
                    $module = request()->module();
                }

                // 查询行为,判断是否执行
                $action_info = model('admin/action')->where('module', $module)->getByName($action);
                if ($action_info['status'] != 1) {
                    return '该行为被禁用或删除';
                }

                // 插入行为日志
                $data = [
                    'action_id'   => $action_info['id'],
                    'user_id'     => $user_id,
                    'action_ip'   => get_client_ip(1),
                    'model'       => $model,
                    'record_id'   => $record_id,
                    'create_time' => request()->time()
                ];

                // 解析日志规则,生成日志备注
                if (!empty($action_info['log'])) {
                    if (preg_match_all('/\[(\S+?)\]/', $action_info['log'], $match)) {
                        $log = [
                            'user'    => $user_id,
                            'record'  => $record_id,
                            'model'   => $model,
                            'time'    => request()->time(),
                            'data'    => [
                                'user'   => $user_id,
                                'model'  => $model,
                                'record' => $record_id,
                                'time'   => request()->time()
                            ],
                            'details' => $details
                        ];

                        $replace = [];
                        foreach ($match[1] as $value) {
                            $param = explode('|', $value);
                            if (isset($param[1])) {
                                $replace[] = call_user_func($param[1], $log[$param[0]]);
                            } else {
                                $replace[] = $log[$param[0]];
                            }
                        }

                        $data['remark'] = str_replace($match[0], $replace, $action_info['log']);
                    } else {
                        $data['remark'] = $action_info['log'];
                    }
                } else {
                    // 未定义日志规则，记录操作url
                    $data['remark'] = '操作url：' . $_SERVER['REQUEST_URI'];
                }

                // 保存日志
                model('admin/log')->insert($data);

                if (!empty($action_info['rule'])) {
                    // 解析行为
                    $rules = parse_action($action, $user_id);
                    // 执行行为
                    $res = execute_action($rules, $action_info['id'], $user_id);
                    if (!$res) {
                        return '执行行为失败';
                    }
                }
            }

            return true;
        }
    }

    if (!function_exists('parse_action')) {
        /**
         * 解析行为规则
         * 规则定义  table:$table|field:$field|condition:$condition|rule:$rule[|cycle:$cycle|max:$max][;......]
         * 规则字段解释：table->要操作的数据表，不需要加表前缀；
         *            field->要操作的字段；
         *            condition->操作的条件，目前支持字符串，默认变量{$self}为执行行为的用户
         *            rule->对字段进行的具体操作，目前支持四则混合运算，如：1+score*2/2-3
         *            cycle->执行周期，单位（小时），表示$cycle小时内最多执行$max次
         *            max->单个周期内的最大执行次数（$cycle和$max必须同时定义，否则无效）
         * 单个行为后可加 ； 连接其他规则
         *
         * @param string $action 行为id或者name
         * @param int $self 替换规则里的变量为执行用户的id
         *
         * @author huajie <banhuajie@163.com>
         * @alter  蔡伟明 <314013107@qq.com>
         * @return boolean|array: false解析出错 ， 成功返回规则数组
         */
        function parse_action($action = null, $self)
        {

            if (empty($action)) {
                return false;
            }

            // 参数支持id或者name
            if (is_numeric($action)) {
                $map = ['id' => $action];
            } else {
                $map = ['name' => $action];
            }

            // 查询行为信息
            $info = model('admin/action')->where($map)->find();
            if (!$info || $info['status'] != 1) {
                return false;
            }

            // 解析规则:table:$table|field:$field|condition:$condition|rule:$rule[|cycle:$cycle|max:$max][;......]
            $rule   = $info['rule'];
            $rule   = str_replace('{$self}', $self, $rule);
            $rules  = explode(';', $rule);
            $return = [];
            foreach ($rules as $key => &$rule) {
                $rule = explode('|', $rule);
                foreach ($rule as $k => $fields) {
                    $field = empty($fields) ? [] : explode(':', $fields);
                    if (!empty($field)) {
                        $return[$key][$field[0]] = $field[1];
                    }
                }
                // cycle(检查周期)和max(周期内最大执行次数)必须同时存在，否则去掉这两个条件
                if (!isset($return[$key]['cycle']) || !isset($return[$key]['max'])) {
                    unset($return[$key]['cycle'], $return[$key]['max']);
                }
            }

            return $return;
        }
    }

    if (!function_exists('execute_action')) {
        /**
         * 执行行为
         *
         * @param array|bool $rules 解析后的规则数组
         * @param int $action_id 行为id
         * @param array $user_id 执行的用户id
         *
         * @author huajie <banhuajie@163.com>
         * @alter  蔡伟明 <314013107@qq.com>
         * @return boolean false 失败 ， true 成功
         */
        function execute_action($rules = false, $action_id = null, $user_id = null)
        {

            if (!$rules || empty($action_id) || empty($user_id)) {
                return false;
            }

            $return = true;
            foreach ($rules as $rule) {
                // 检查执行周期
                $map                = ['action_id' => $action_id, 'user_id' => $user_id];
                $map['create_time'] = ['gt', request()->time() - intval($rule['cycle']) * 3600];
                $exec_count         = model('admin/log')->where($map)->count();
                if ($exec_count > $rule['max']) {
                    continue;
                }

                // 执行数据库操作
                $field = $rule['field'];
                $res   = Db::name($rule['table'])->where($rule['condition'])->setField($field, ['exp', $rule['rule']]);

                if (!$res) {
                    $return = false;
                }
            }
            return $return;
        }
    }

    if (!function_exists('get_location')) {
        /**
         * 获取当前位置
         *
         * @param string $id 节点id，如果没有指定，则取当前节点id
         * @param bool $del_last_url 是否删除最后一个节点的url地址
         * @param bool $check 检查节点是否存在，不存在则抛出错误
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return mixed
         */
        function get_location($id = '', $del_last_url = false, $check = true)
        {

            $location = model('admin/menu')->getLocation($id, $del_last_url, $check);
            return $location;
        }
    }

    if (!function_exists('packet_exists')) {
        /**
         * 查询数据包是否存在，即是否已经安装
         *
         * @param string $name 数据包名
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return bool
         */
        function packet_exists($name = '')
        {

            if (Db::name('admin_packet')->where('name', $name)->find()) {
                return true;
            } else {
                return false;
            }
        }
    }

    if (!function_exists('load_assets')) {
        /**
         * 加载静态资源
         *
         * @param string $assets 资源名称
         * @param string $type 资源类型
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return string
         */
        function load_assets($assets = '', $type = 'css')
        {

            $assets_list = config('assets.' . $assets);

            $result = '';
            foreach ($assets_list as $item) {
                if ($type == 'css') {
                    $result .= '<link rel="stylesheet" href="' . $item . '?v=' . config('asset_version') . '">';
                } else {
                    $result .= '<script src="' . $item . '?v=' . config('asset_version') . '"></script>';
                }
            }

            $result = str_replace(array_keys(config('template.tpl_replace_string')), array_values(config('template.tpl_replace_string')), $result);
            return $result;
        }
    }

    if (!function_exists('parse_name')) {
        /**
         * 字符串命名风格转换
         * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格
         *
         * @param string $name 字符串
         * @param integer $type 转换类型
         *
         * @return string
         */
        function parse_name($name, $type = 0)
        {

            if ($type) {
                return ucfirst(preg_replace_callback('/_([a-zA-Z])/', function ($match) {

                    return strtoupper($match[1]);
                }, $name));
            } else {
                return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_"));
            }
        }
    }

    if (!function_exists('home_url')) {
        /**
         * 生成前台入口url
         *
         * @param string $url 路由地址
         * @param string|array $vars 变量
         * @param bool|string $suffix 生成的URL后缀
         * @param bool|string $domain 域名
         *
         * @author 小乌 <82950492@qq.com>
         * @return string
         */
        function home_url($url = '', $vars = '', $suffix = true, $domain = false)
        {

            $url = url($url, $vars, $suffix, $domain);
            if (\think\facade\Env::get('ENTRANCE') == 'admin') {
                $base_file = request()->baseFile();
                $base_file = substr($base_file, strripos($base_file, '/') + 1);
                return preg_replace('/\/' . $base_file . '/', '/index.php', $url);
            } else {
                return $url;
            }
        }
    }

    if (!function_exists('admin_url')) {
        /**
         * 生成后台入口url
         *
         * @param string $url 路由地址
         * @param string|array $vars 变量
         * @param bool|string $suffix 生成的URL后缀
         * @param bool|string $domain 域名
         *
         * @author 小乌 <82950492@qq.com>
         * @return string
         */
        function admin_url($url = '', $vars = '', $suffix = true, $domain = false)
        {

            $url = url($url, $vars, $suffix, $domain);
            if (\think\facade\Env::get('ENTRANCE') == 'admin') {
                return $url;
            } else {
                return preg_replace('/\/index.php/', '/' . \think\facade\Env::set('ADMIN_FILE', 'admin.php'), $url);
            }
        }
    }
    if (!function_exists('htmlpurifier')) {
        /**
         * html安全过滤
         *
         * @param string $html 要过滤的内容
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return string
         */
        function htmlpurifier($html = '')
        {

            $config     = HTMLPurifier_Config::createDefault();
            $purifier   = new HTMLPurifier($config);
            $clean_html = $purifier->purify($html);
            return $clean_html;
        }
    }

    if (!function_exists('extend_form_item')) {
        /**
         * 扩展表单项
         *
         * @param array $form 类型
         * @param array $_layout 布局参数
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return string
         */
        function extend_form_item($form = [], $_layout = [])
        {

            if (!isset($form['type']))
                return '';
            if (!empty($_layout) && isset($_layout[$form['name']])) {
                $form['_layout'] = $_layout[$form['name']];
            }

            $template = './extend/form/' . $form['type'] . '/' . $form['type'] . '.html';
            if (file_exists($template)) {
                $template_content = file_get_contents($template);
                $view             = new View();
                return $view->display($template_content, $form);
            } else {
                return '';
            }
        }
    }

    if (!function_exists('role_auth')) {
        /**
         * 读取当前用户权限
         *
         * @author 蔡伟明 <314013107@qq.com>
         */
        function role_auth()
        {

            session('role_menu_auth', model('user/role')->roleAuth());
        }
    }

    if (!function_exists('get_server_ip')) {
        /**
         * 获取服务器端IP地址
         *
         * @return array|false|string
         */
        function get_server_ip()
        {

            if (isset($_SERVER)) {
                if ($_SERVER['SERVER_ADDR']) {
                    $server_ip = $_SERVER['SERVER_ADDR'];
                } else {
                    $server_ip = $_SERVER['LOCAL_ADDR'];
                }
            } else {
                $server_ip = getenv('SERVER_ADDR');
            }
            return $server_ip;
        }
    }

    if (!function_exists('get_browser_type')) {
        /**
         * 获取浏览器类型
         *
         * @return string
         */
        function get_browser_type()
        {

            $agent = $_SERVER["HTTP_USER_AGENT"];
            if (strpos($agent, 'MSIE') !== false || strpos($agent, 'rv:11.0'))
                return "ie";
            if (strpos($agent, 'Firefox') !== false)
                return "firefox";
            if (strpos($agent, 'Chrome') !== false)
                return "chrome";
            if (strpos($agent, 'Opera') !== false)
                return 'opera';
            if ((strpos($agent, 'Chrome') == false) && strpos($agent, 'Safari') !== false)
                return 'safari';
            if (false !== strpos($_SERVER['HTTP_USER_AGENT'], '360SE'))
                return '360SE';
            return 'unknown';
        }
    }

    if (!function_exists('generate_rand_str')) {
        /**
         * 生成随机字符串
         *
         * @param int $length 生成长度
         * @param int $type 生成类型：0-小写字母+数字，1-小写字母，2-大写字母，3-数字，4-小写+大写字母，5-小写+大写+数字
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return string
         */
        function generate_rand_str($length = 8, $type = 0)
        {

            $a = 'abcdefghijklmnopqrstuvwxyz';
            $A = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
            $n = '0123456789';

            switch ($type) {
                case 1:
                    $chars = $a;
                    break;
                case 2:
                    $chars = $A;
                    break;
                case 3:
                    $chars = $n;
                    break;
                case 4:
                    $chars = $a . $A;
                    break;
                case 5:
                    $chars = $a . $A . $n;
                    break;
                default:
                    $chars = $a . $n;
            }

            $str = '';
            for ($i = 0; $i < $length; $i++) {
                $str .= $chars[mt_rand(0, strlen($chars) - 1)];
            }
            return $str;
        }
    }

    if (!function_exists('dp_send_message')) {
        /**
         * 发送消息给用户
         *
         * @param string $type 消息类型
         * @param string $content 消息内容
         * @param string $uids 用户id，可以是数组，也可以是逗号隔开的字符串
         *
         * @author 蔡伟明 <314013107@qq.com>
         * @return bool
         */
        function dp_send_message($type = '', $content = '', $uids = '')
        {

            $uids = is_array($uids) ? $uids : explode(',', $uids);
            $list = [];
            foreach ($uids as $uid) {
                $list[] = [
                    'uid_receive' => $uid,
                    'uid_send'    => \think\facade\Env::get('UID'),
                    'type'        => $type,
                    'content'     => $content,
                ];
            }

            $MessageModel = model('user/message');
            return false !== $MessageModel->saveAll($list);
        }
    }
